#!/usr/bin/env bash
#
# @license Apache-2.0
#
# Copyright (c) 2017 The Stdlib Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Uses browserify to generate a test bundle for each package with tests.
#
# This script is called with the following arguments:
#
# * `$1` - destination directory


# VARIABLES #

# Destination directory for package bundles:
output_dir="$1"
if [[ -z "${output_dir}" ]]; then
	echo 'ERROR: Must provide a destination directory.' >&2
	exit 1
fi

# Determine root directory:
root_dir="$(git rev-parse --show-toplevel)"

# Define the path to a utility for finding packages:
find_packages="${root_dir}/tools/scripts/find_packages"

# Determine the host kernel:
kernel=$(uname -s)

# Define the path to the source library:
source_dir="${root_dir}/lib/node_modules"

# Define the path to node modules:
node_modules="${root_dir}/node_modules"

# Define the path to `browserify`:
browserify="${node_modules}/.bin/browserify"

# Define the path to the `browserify` transform to replace Node-style environment variables with strings:
browserify_envify="${node_modules}/envify"

# Define the path to the `browserify` plugin which allows `proxyquire` to be run in a browser:
browserify_proxyquire="${node_modules}/proxyquire-universal"

# Define the pattern for test filenames:
tests_pattern='test*.js'


# FUNCTIONS #

# Defines an error handler.
#
# $1 - error status
on_error() {
	echo 'ERROR: An error was encountered during execution.' >&2
	cleanup
	exit "$1"
}

# Runs clean-up tasks.
cleanup() {
	echo ''
}

# Creates a directory.
#
# $1 - directory path
create_dir() {
	mkdir -p "$1"
}

# Prints a success message.
print_success() {
	echo 'Success!' >&2
}

# Finds tests.
#
# $1 - search directory
find_tests() {
	local files

	echo 'Searching for tests...' >&2

	# On Mac OSX, in order to use `|` and other regular expression operators, we need to use enhanced regular expression syntax (-E); see https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man7/re_format.7.html#//apple_ref/doc/man/7/re_format.
	if [[ "${kernel}" == "Darwin" ]]; then
		files=$(find -E "$1" -name "${tests_pattern}")
	else
		files=$(find "$1" -regextype posix-extended -name "${tests_pattern}")
	fi
	echo "${files}"
	return 0
}

# Extracts a package name from an absolute file path.
#
# $1 - file path
package_name() {
	local name

	# Remove the source directory path from the package path (using POSIX shell variable expansion):
	if [[ "$1" == "${root_dir}" ]]; then
		name='@stdlib/stdlib'
	else
		name="${1#${source_dir}/}"
	fi
	echo "${name}"
}

# Creates test bundles.
#
# $1 - packages
create_bundles() {
	local files
	local dest
	local name
	local src

	echo 'Creating test bundles...' >&2
	echo '' >&2

	for pkg in $(echo "$1"); do
		echo "Package: ${pkg}" >&2

		src="${pkg}/test"
		name=$(package_name "${pkg}")

		files=$(find_tests "${src}")
		if [[ "$?" -ne 0 ]]; then
			echo "Encountered an error when searching for package tests: ${pkg}.". >&2
			return 1
		fi

		if [[ -n "${files}" ]]; then
			dest="${output_dir}/${name}"
			create_dir "${dest}"

			create_bundle "${files}" "${dest}/test_bundle.js"
			if [[ "$?" -ne 0 ]]; then
				echo "Encountered an error when creating package bundle: ${pkg}.". >&2
				return 1
			fi
			echo 'Successfully created package bundle.' >&2
		else
			echo 'No tests. Skipping package.' >&2
		fi
		echo '' >&2
	done
	echo 'Finished creating bundles.' >&2
	return 0
}

# Creates a bundle.
#
# $1 - source files
# $2 - destination
create_bundle() {
	"${browserify}" "-t=${browserify_envify}" "-p=${browserify_proxyquire}" $(echo "$1") > "$2"
}

# Main execution sequence:
main() {
	local pkgs

	pkgs=$("${find_packages}")
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	create_bundles "${pkgs}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	print_success
	cleanup
	exit 0
}

# Run main:
main
